<html>
<head><meta charset="utf-8"><title>Should copy types always be passed by value? · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html">Should copy types always be passed by value?</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="225485981"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225485981" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Elichai Turkel <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225485981">(Feb 07 2021 at 21:53)</a>:</h4>
<p>I know that in some languages passing by value always means copying if the function isn't inlined,<br>
in rust can we assume that the compiler can always optimize it to passing by reference if it's not mutated? such that even <code>[u128; 2048]</code> can be safely passed by value around without fear of big copies?</p>



<a name="225487983"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225487983" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> erikdesjardins <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225487983">(Feb 07 2021 at 22:38)</a>:</h4>
<p>for this (simple) code it's copied into each stack frame <a href="https://godbolt.org/z/466x4n">https://godbolt.org/z/466x4n</a><br>
i'd say "no"</p>



<a name="225525788"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225525788" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Elichai Turkel <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225525788">(Feb 08 2021 at 10:36)</a>:</h4>
<p>ha. that's interesting.<br>
Are there any rules of thumbs here?</p>
<p>Also, why doesn't the C one copies the array?</p>



<a name="225530297"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225530297" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Giacomo Stevanato <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225530297">(Feb 08 2021 at 11:24)</a>:</h4>
<blockquote>
<p>can we assume that the compiler can always optimize it to passing by reference if it's not mutated</p>
</blockquote>
<p>Generally, no. <code>Copy</code> types are generally pretty small, so small that the cost of passing a pointer and dereferencing it will likely be bigger than making a copy. </p>
<blockquote>
<p>Also, why doesn't the C one copies the array?</p>
</blockquote>
<p>I guess clang's own optimizations. Note that gcc also produces <code>memcpy</code>s.</p>



<a name="225530534"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225530534" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225530534">(Feb 08 2021 at 11:27)</a>:</h4>
<p>Yeah, currently Rust is rather bad at optimizing away copies</p>



<a name="225530570"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225530570" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225530570">(Feb 08 2021 at 11:27)</a>:</h4>
<p>I think if you pass a non-<code>Copy</code> value to a function we'll always pass by reference, but not otherwise</p>



<a name="225532037"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225532037" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225532037">(Feb 08 2021 at 11:43)</a>:</h4>
<p>Non-<code>Copy</code> values will also be passed by value if the ABI requires it. For example wrappers around integers are often passed by-value. The x86_64 System-V abi is also very aggressive in packing structs in one or two registers. Even when there are more fields. Beyond that for the "Rust" abi, types of at most two registers are often passed by-value.</p>



<a name="225532222"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225532222" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Giacomo Stevanato <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225532222">(Feb 08 2021 at 11:45)</a>:</h4>
<blockquote>
<p>Yeah, currently Rust is rather bad at optimizing away copies</p>
</blockquote>
<p>To be fair, so is gcc. I think rust could support it by  using LLVM's <code>byval</code> attribute, but I don't know why it currently doesnt.</p>



<a name="225532344"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225532344" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225532344">(Feb 08 2021 at 11:47)</a>:</h4>
<p><code>byval</code> is used when the ABI requires it.</p>



<a name="225532487"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225532487" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225532487">(Feb 08 2021 at 11:48)</a>:</h4>
<p>The disadvantage of using <code>byval</code> is that it forces the value to be at a specific stack location, which means that a <code>memcpy</code> would be necessary if something else needed to be stored at that location previously.</p>



<a name="225536335"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225536335" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Giacomo Stevanato <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225536335">(Feb 08 2021 at 12:27)</a>:</h4>
<p>But aren't we already doing a <code>memcpy</code> anyway?</p>



<a name="225537325"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225537325" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225537325">(Feb 08 2021 at 12:36)</a>:</h4>
<p>Yes, in this case it requires a <code>memcpy</code> at the callee side, but it may not always need it. At least when you don't pass the argument to another function it isn't needed. However when using <code>byval</code>, there must almost always be a copy on the caller. In that case it is not possible to decide to not do a <code>memcpy</code> when the callee doesn't pass it as argument to another function.</p>



<a name="225539452"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Should%20copy%20types%20always%20be%20passed%20by%20value%3F/near/225539452" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Should.20copy.20types.20always.20be.20passed.20by.20value.3F.html#225539452">(Feb 08 2021 at 12:55)</a>:</h4>
<p>There is something odd / curious here: if we forget about the wrappers and just look at <code>sum</code> in <a href="https://godbolt.org/z/znc9Kc">https://godbolt.org/z/znc9Kc</a>, using <code>ByVal { x }: ByVal</code> or <code>ByVal { ref x }: ByVal</code> does change the implementation (alloca in the llvm-ir only for the former), even with <code>panic = "abort"</code> and <code>opt-level=3</code> for both cases. I'd have expected the second case to be equivalent to <code>arg: ByVal</code> followed by a <code>let ByVal { ref x } = arg;</code> which would have been equivalent to doing <code>let x = &amp;arg.x</code> which, by inlining that expression, should be equivalent to the first case <span aria-label="shrug" class="emoji emoji-1f937" role="img" title="shrug">:shrug:</span></p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>